import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import {
  IsArray,
  IsBoolean,
  IsNumber,
  IsObject,
  IsOptional,
  IsString,
  Max,
  Min,
  ValidateNested,
} from 'class-validator';
import { Type } from 'class-transformer';

/**
 * 文本内容DTO
 */
export class TextContentDto {
  /**
   * 内容类型
   */
  @ApiProperty({
    description: '内容类型',
    example: 'text',
  })
  @IsString()
  type: string;

  /**
   * 文本内容
   */
  @ApiProperty({
    description: '文本内容',
    example: '这张图片是什么？',
  })
  @IsString()
  text: string;
}

/**
 * 图像URL DTO
 */
export class ImageUrlDto {
  /**
   * 图像URL
   */
  @ApiProperty({
    description: '图像URL',
    example: 'https://example.com/image.jpg',
  })
  @IsString()
  url: string;
}

/**
 * 图像内容DTO
 */
export class ImageContentDto {
  /**
   * 内容类型
   */
  @ApiProperty({
    description: '内容类型',
    example: 'image_url',
  })
  @IsString()
  type: string;

  /**
   * 图像URL信息
   */
  @ApiProperty({
    description: '图像URL信息',
    type: ImageUrlDto,
  })
  @ValidateNested()
  @Type(() => ImageUrlDto)
  image_url: ImageUrlDto;
}

/**
 * 聊天消息DTO
 */
export class DeepSeekChatMessageDto {
  /**
   * 消息角色（用户、助手或系统）
   */
  @ApiProperty({
    description: '消息角色',
    enum: ['user', 'assistant', 'system'],
    example: 'user',
  })
  @IsString()
  role: string;

  /**
   * 消息内容 - 可以是字符串或内容对象数组
   */
  @ApiProperty({
    description: '消息内容',
    oneOf: [
      { type: 'string' },
      {
        type: 'array',
        items: {
          oneOf: [
            { $ref: '#/components/schemas/TextContentDto' },
            { $ref: '#/components/schemas/ImageContentDto' },
          ],
        },
      },
    ],
    example: '你好，请解释一下量子计算的基本原理。',
  })
  content: string | (TextContentDto | ImageContentDto)[];
}

/**
 * DeepSeek聊天完成请求DTO
 */
export class DeepSeekChatCompletionRequestDto {
  /**
   * 要使用的模型ID
   */
  @ApiProperty({
    description: '要使用的模型ID',
    example: 'deepseek-chat',
  })
  @IsString()
  model: string;

  /**
   * 聊天消息列表
   */
  @ApiProperty({
    description: '聊天消息列表',
    type: [DeepSeekChatMessageDto],
  })
  @IsArray()
  messages: DeepSeekChatMessageDto[];

  /**
   * 是否启用结果流式传输
   */
  @ApiPropertyOptional({
    description: '是否启用结果流式传输',
    default: false,
    example: false,
  })
  @IsOptional()
  @IsBoolean()
  stream?: boolean;

  /**
   * 最大生成令牌数
   */
  @ApiPropertyOptional({
    description: '生成响应的最大token数',
    minimum: 1,
    example: 2000,
  })
  @IsOptional()
  @IsNumber()
  @Min(1)
  max_tokens?: number;

  /**
   * 采样温度，控制输出的随机性
   */
  @ApiPropertyOptional({
    description: '采样温度，控制输出的随机性',
    minimum: 0,
    maximum: 2,
    default: 0.7,
    example: 0.7,
  })
  @IsOptional()
  @IsNumber()
  @Min(0)
  @Max(2)
  temperature?: number;

  /**
   * 确定性输出的种子
   */
  @ApiPropertyOptional({
    description: '确定性输出的种子',
    example: 42,
  })
  @IsOptional()
  @IsNumber()
  seed?: number;

  /**
   * Top-p采样值
   */
  @ApiPropertyOptional({
    description: 'Top-p采样值',
    minimum: 0,
    maximum: 1,
    default: 0.9,
    example: 0.9,
  })
  @IsOptional()
  @IsNumber()
  @Min(0)
  @Max(1)
  top_p?: number;

  /**
   * Top-k采样值
   */
  @ApiPropertyOptional({
    description: 'Top-k采样值',
    minimum: 1,
    example: 40,
  })
  @IsOptional()
  @IsNumber()
  @Min(1)
  top_k?: number;

  /**
   * 频率惩罚
   */
  @ApiPropertyOptional({
    description: '频率惩罚',
    minimum: -2,
    maximum: 2,
    default: 0,
    example: 0,
  })
  @IsOptional()
  @IsNumber()
  @Min(-2)
  @Max(2)
  frequency_penalty?: number;

  /**
   * 存在惩罚
   */
  @ApiPropertyOptional({
    description: '存在惩罚',
    minimum: -2,
    maximum: 2,
    default: 0,
    example: 0,
  })
  @IsOptional()
  @IsNumber()
  @Min(-2)
  @Max(2)
  presence_penalty?: number;

  /**
   * 重复惩罚
   */
  @ApiPropertyOptional({
    description: '重复惩罚',
    minimum: 0,
    maximum: 2,
    example: 1.1,
  })
  @IsOptional()
  @IsNumber()
  @Min(0)
  @Max(2)
  repetition_penalty?: number;

  /**
   * 词元ID到偏置值的映射
   */
  @ApiPropertyOptional({
    description: '词元ID到偏置值的映射',
    type: 'object',
    example: { '50256': -100 },
  })
  @IsOptional()
  @IsObject()
  logit_bias?: Record<string, number>;
}
